package net.simflow.swf.analyzer.gui;

import java.util.ArrayList;
import java.util.Map.Entry;

import net.simflow.swf.analyzer.data.StringConstant;
import net.simflow.swf.analyzer.data.TupleStrInt;
import net.simflow.swf.analyzer.opt.FontDataClone;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Display;

import edu.uci.ics.jung.algorithms.util.BasicMapEntry;

public class Printer {
	private static final String NEW_LINE = "\n\n";
	private static final String TAB = "\n\t";

	public static final int COLOR_WARNING = SWT.COLOR_DARK_BLUE;
	public static final int COLOR_ERROR = SWT.COLOR_DARK_RED;

	private static Printer instance = new Printer();

	private Printer() {
	}

	public static Printer getInstance() {
		return instance;
	}

	public void clear(final StyledText text) {
		if (text == null) {
			return;
		}
		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				text.setText("");
			}
		});
	}

	public void set(final StyledText text,
			final ArrayList<TupleStrInt> strList, final int color) {
		if (text == null) {
			return;
		}
		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				clear(text);
				append(text, strList, color);
				text.setTopIndex(0);
			}
		});
	}

	public void append(final StyledText text,
			final ArrayList<TupleStrInt> strList, final int color) {
		if (text == null) {
			return;
		}
		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				StringBuffer strb = new StringBuffer();
				ArrayList<StyleRange> list = new ArrayList<StyleRange>();
				for (Entry<String, Integer> en : strList) {
					Entry<StringBuffer, StyleRange> r = makeLine(text.getText()
							.length() + strb.length(), en.getKey(),
							en.getValue(), color);
					strb.append(r.getKey());
					list.add(r.getValue());
				}

				text.append(strb.toString());
				for (StyleRange sr : list) {
					text.setStyleRange(sr);
				}

				text.setTopIndex(Integer.MAX_VALUE);
			}
		});
	}

	public void append(final StyledText text, final String str,
			final int style, final int color) {
		if (text == null) {
			return;
		}
		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				Entry<StringBuffer, StyleRange> r = makeLine(text.getText()
						.length(), str, style, color);
				StringBuffer strb = r.getKey();
				StyleRange styleRange = r.getValue();

				text.append(strb.toString());
				text.setStyleRange(styleRange);
				text.setTopIndex(Integer.MAX_VALUE);
			}
		});
	}

	private Entry<StringBuffer, StyleRange> makeLine(final int start,
			final String str, final int style, final int color) {
		if (str == null || str.length() <= 0) {
			return null;
		}

		final StringBuffer strb = new StringBuffer();
		final Entry<StringBuffer, StyleRange> result = new BasicMapEntry<StringBuffer, StyleRange>(
				strb, null);

		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				StyleRange styleRange = null;
				switch (style) {
				case StringConstant.ERROR:
					if (start != 0) {
						strb.append(NEW_LINE);
					}
					strb.append("ERROR: ").append(str);
					styleRange = new StyleRange(start, strb.length(), Display
							.getCurrent().getSystemColor(color), null);
					break;
				case StringConstant.WARNING:
					if (start != 0) {
						strb.append(NEW_LINE);
					}
					strb.append("WARNING: ").append(str);
					styleRange = new StyleRange(start, strb.length(), Display
							.getCurrent().getSystemColor(color), null);
					break;
				case StringConstant.PKG_TITLE:
					if (start != 0) {
						strb.append(NEW_LINE);
					}
					strb.append(str);
					FontData fontData = FontDataClone.clone(Display
							.getCurrent().getSystemFont().getFontData()[0]);
					fontData.setHeight(fontData.getHeight() + 2);
					fontData.setStyle(SWT.BOLD);
					Font font = new Font(Display.getCurrent(), fontData);
					styleRange = new StyleRange(start, strb.length(), Display
							.getCurrent().getSystemColor(SWT.COLOR_BLACK),
							null, SWT.BOLD);
					styleRange.font = font;
					break;
				case StringConstant.TITLE:
					if (start != 0) {
						strb.append(NEW_LINE);
					}
					strb.append(str);
					styleRange = new StyleRange(start, strb.length(), Display
							.getCurrent().getSystemColor(color), null, SWT.BOLD);
					break;
				case StringConstant.CONTENT:
					if (start != 0) {
						strb.append(TAB);
					}
					strb.append(str);
					styleRange = new StyleRange(start, strb.length(), Display
							.getCurrent().getSystemColor(color), null);
					break;
				}

				if (styleRange != null && strb.length() > 0) {
					result.setValue(styleRange);
				}
			}
		});

		if (result.getValue() != null && strb.length() > 0) {
			return result;
		} else {
			return null;
		}
	}
}
